package cn.bby.tools.dialog;

import cn.bby.tools.dialog.common.BaseResultDisplayDialog;
import cn.bby.tools.service.StateManagementService;
import cn.bby.tools.utils.ClassChooseUtil;
import cn.bby.tools.utils.ClassDataMockUtil;
import cn.bby.tools.utils.MessageUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.util.ui.JBUI;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;

import static cn.bby.tools.utils.ClassChooseUtil.detectCurrentClass;
import static cn.bby.tools.utils.ClassChooseUtil.findClass;
import static cn.bby.tools.utils.ClassDataMockUtil.FUTURE;
import static cn.bby.tools.utils.ClassDataMockUtil.NOW;
import static cn.bby.tools.utils.ClassDataMockUtil.PAST;

/**
 * 生成Mock数据对话框
 * 用于根据实体类生成JSON格式的mock数据
 *
 * @author ben
 * @version 1.0
 */
public class GenMockDataDialog extends BaseResultDisplayDialog {

    // 项目和编辑器相关
    private final Project project;
    private final Editor editor;
    private final GenMockDataState genMockDataState;
    
    // UI组件
    private final JTextField classField = new JTextField(30);
    private JTextField stringDefaultValueField;
    private JCheckBox stringRandomCheckBox;
    private JTextField intMinValueField;
    private JTextField intMaxValueField;
    private JComboBox<String> timeValueComboBox;
    private JTextField timeFormatField;
    private JCheckBox timestampCheckBox;
    private JCheckBox nestedMockCheckBox;

    // 业务数据
    private PsiClass selectedClass;

    /**
     * 构造函数
     *
     * @param project          项目实例
     * @param editor           当前编辑器
     */
    public GenMockDataDialog(@Nullable Project project, @Nullable Editor editor) {
        super(project, MessageUtil.getMessage("action.BBY.GenMockDataAction.text"));
        this.project = project;
        this.editor = editor;
        this.genMockDataState = StateManagementService.getInstanceState().genMockDataState;
        init();
    }

    /**
     * 设置上次选中的类
     *
     * @param qualifiedName 类全限定名
     */
    public void setLastSelectedClass(String qualifiedName) {
        if (qualifiedName != null && !qualifiedName.isEmpty()) {
            PsiClass psiClass = findClass(project, qualifiedName);
            if (psiClass != null) {
                this.selectedClass = psiClass;
            }
        }
    }

    @Override
    protected @Nullable JComponent createCenterPanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = JBUI.insets(5);
        gbc.anchor = GridBagConstraints.WEST;

        // 创建组件
        initializeFields();

        // 创建按钮
        JButton selectClassButton = new JButton(MessageUtil.getMessage("message.SelectClass","..."));
        JButton generateButton = new JButton(MessageUtil.getMessage("message.Generate"));

        // 添加类选择行
        addClassSelectionRow(panel, gbc, selectClassButton);

        // 添加配置行
        addConfigurationRows(panel, gbc);

        // 添加生成按钮
        addGenerateButton(panel, gbc, generateButton);

        // 添加结果显示区域
        addResultArea(panel, gbc);

        // 添加事件监听器
        addEventListeners(selectClassButton, generateButton);

        return panel;
    }

    /**
     * 初始化选中的类
     */
    private void initSelectClass() {
        PsiClass currentClass = detectCurrentClass(project, editor);
        if (currentClass != null) {
            selectedClass = currentClass;
            classField.setText(currentClass.getQualifiedName());
        } else if (StrUtil.isNotBlank(genMockDataState.lastSelectedClass)) {
            selectedClass = findClass(project, genMockDataState.lastSelectedClass);
            if (selectedClass != null) {
                classField.setText(selectedClass.getQualifiedName());
            }
        }
    }

    /**
     * 初始化配置字段
     */
    private void initializeFields() {
        stringDefaultValueField = new JTextField(genMockDataState.stringDefaultValue, 15);
        stringRandomCheckBox = new JCheckBox();
        stringRandomCheckBox.setSelected(genMockDataState.stringRandom);
        intMinValueField = new JTextField(genMockDataState.intMinValue, 5);
        intMaxValueField = new JTextField(genMockDataState.intMaxValue, 5);
        timeValueComboBox = new JComboBox<>(new String[]{NOW, PAST, FUTURE});
        
        // 设置时间值选项
        switch (genMockDataState.timeValue) {
            case NOW:
                timeValueComboBox.setSelectedIndex(0);
                break;
            case FUTURE:
                timeValueComboBox.setSelectedIndex(2);
                break;
            case PAST:
            default:
                timeValueComboBox.setSelectedIndex(1);
                break;
        }
        
        timeFormatField = new JTextField(genMockDataState.timeFormat, 15);
        timestampCheckBox = new JCheckBox();
        timestampCheckBox.setSelected(genMockDataState.timestamp);
        nestedMockCheckBox = new JCheckBox(MessageUtil.getMessage("message.NestedMock"), genMockDataState.nestedMock);
    }

    /**
     * 生成Mock数据
     *
     * @param psiClass 目标类
     * @return JSON字符串
     */
    private JSONObject generateMockData(PsiClass psiClass) {
        try {
            String stringDefaultValue = stringDefaultValueField.getText();
            boolean stringRandom = stringRandomCheckBox.isSelected();
            
            int intMinValue = Integer.parseInt(intMinValueField.getText());
            int intMaxValue = Integer.parseInt(intMaxValueField.getText());
            
            String timeValue = (String) timeValueComboBox.getSelectedItem();
            String timeFormat = timeFormatField.getText();
            boolean timestamp = timestampCheckBox.isSelected();
            boolean nestedMock = nestedMockCheckBox.isSelected();
            
            return ClassDataMockUtil.generateMockData(
                    new ClassDataMockUtil.GenMockParam(project, psiClass, stringDefaultValue, stringRandom, intMinValue,
                            intMaxValue, timeValue, timeFormat, timestamp, nestedMock));
        } catch (NumberFormatException e) {
            // 使用默认值
            return ClassDataMockUtil.generateMockData(
                    new ClassDataMockUtil.GenMockParam(project, psiClass, true));
        }
    }

    /**
     * 将文本复制到剪贴板
     *
     * @param text 要复制的文本
     */
    private void copyToClipboard(String text) {
        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        StringSelection selection = new StringSelection(text);
        clipboard.setContents(selection, null);
    }

    /**
     * 获取选中的类
     *
     * @return 选中的类
     */
    public PsiClass getSelectedClass() {
        return selectedClass;
    }

    /**
     * 添加类选择行
     *
     * @param panel             面板
     * @param gbc               网格约束
     * @param selectClassButton 选择类按钮
     */
    private void addClassSelectionRow(JPanel panel, GridBagConstraints gbc, JButton selectClassButton) {
        gbc.gridx = 0;
        gbc.gridy = 0;
        panel.add(new JLabel(MessageUtil.getMessage("message.targetclass")), gbc);

        gbc.gridx = 1;
        gbc.weightx = 1.0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridwidth = 2;
        classField.setEditable(false);
        // 如果已检测到类，设置显示
        // 自动检测当前焦点所在的类
        initSelectClass();
        panel.add(classField, gbc);

        gbc.gridx = 3;
        gbc.weightx = 0;
        gbc.fill = GridBagConstraints.NONE;
        gbc.gridwidth = 1;
        panel.add(selectClassButton, gbc);
    }

    /**
     * 添加配置行
     *
     * @param panel 面板
     * @param gbc   网格约束
     */
    private void addConfigurationRows(JPanel panel, GridBagConstraints gbc) {
        // 字符串配置行
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.gridwidth = 1;
        panel.add(new JLabel(MessageUtil.getMessageSuffix("message.StringDefault")), gbc);

        gbc.gridx = 1;
        gbc.gridwidth = 3;
        JPanel stringPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
        stringPanel.add(stringDefaultValueField);
        stringPanel.add(Box.createHorizontalStrut(5));
        stringPanel.add(stringRandomCheckBox);
        stringPanel.add(new JLabel(MessageUtil.getMessage("message.Random")));
        panel.add(stringPanel, gbc);

        // 数值配置行
        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.gridwidth = 1;
        panel.add(new JLabel(MessageUtil.getMessageSuffix("message.IntegerRange")), gbc);

        gbc.gridx = 1;
        gbc.gridwidth = 3;
        JPanel intPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
        intPanel.add(intMinValueField);
        intPanel.add(new JLabel(" - "));
        intPanel.add(intMaxValueField);
        panel.add(intPanel, gbc);

        // 时间配置行
        gbc.gridx = 0;
        gbc.gridy = 3;
        gbc.gridwidth = 1;
        panel.add(new JLabel(MessageUtil.getMessageSuffix("message.TimeValue")), gbc);

        gbc.gridx = 1;
        panel.add(timeValueComboBox, gbc);

        gbc.gridx = 2;
        JPanel timeFormatPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
        timeFormatPanel.add(new JLabel(MessageUtil.getMessageSuffix("message.TimeFormat")));
        timeFormatPanel.add(timeFormatField);
        timeFormatPanel.add(Box.createHorizontalStrut(5));
        timeFormatPanel.add(timestampCheckBox);
        timeFormatPanel.add(new JLabel(MessageUtil.getMessage("message.Timestamp")));
        panel.add(timeFormatPanel, gbc);

        // 嵌套Mock配置行
        gbc.gridx = 0;
        gbc.gridy = 4;
        gbc.gridwidth = 1;
        panel.add(new JLabel(MessageUtil.getMessage("message.NestedMock")), gbc);

        gbc.gridx = 1;
        gbc.gridwidth = 3;
        panel.add(nestedMockCheckBox, gbc);
    }

    /**
     * 添加生成按钮
     *
     * @param panel          面板
     * @param gbc            网格约束
     * @param generateButton 生成按钮
     */
    private void addGenerateButton(JPanel panel, GridBagConstraints gbc, JButton generateButton) {
        gbc.gridx = 0;
        gbc.gridy = 5;
        gbc.gridwidth = 4;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        panel.add(generateButton, gbc);
    }

    /**
     * 添加结果区域
     *
     * @param panel 面板
     * @param gbc   网格约束
     */
    private void addResultArea(JPanel panel, GridBagConstraints gbc) {
        gbc.gridx = 0;
        gbc.gridy = 6;
        gbc.gridwidth = 4;
        
        // 创建结果标题面板
        JPanel resultTitlePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
        resultTitlePanel.add(new JLabel(MessageUtil.getMessageSuffix("message.Result")));
        resultTitlePanel.add(Box.createHorizontalStrut(10));
        
        // 添加格式化和复制按钮
        JButton formatButton = new JButton(MessageUtil.getMessage("message.format"));
        JButton copyButton = new JButton(MessageUtil.getMessage("message.Copy"));
        resultTitlePanel.add(formatButton);
        resultTitlePanel.add(Box.createHorizontalStrut(5));
        resultTitlePanel.add(copyButton);
        
        panel.add(resultTitlePanel, gbc);

        gbc.gridy = 7;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.weighty = 1.0;
        resultTextArea.setEditable(false);
        resultTextArea.setBorder(BorderFactory.createLoweredBevelBorder());
        JScrollPane scrollPane = new JScrollPane(resultTextArea);
        panel.add(scrollPane, gbc);
        
        // 添加格式化和复制按钮事件监听器
        formatButton.addActionListener(e -> formatResult());
        copyButton.addActionListener(e -> copyResult());
    }
    
    /**
     * 格式化结果
     */
    private void formatResult() {
        String result = resultTextArea.getText();
        if (StrUtil.isNotBlank(result)) {
            try {
                // 这里可以添加格式化逻辑，比如美化JSON格式
                // 目前只是简单地重新设置文本以触发重绘
                resultTextArea.setText(result);
            } catch (Exception ex) {
                // 格式化失败时不做处理
            }
        }
    }
    
    /**
     * 复制结果到剪贴板
     */
    private void copyResult() {
        String result = resultTextArea.getText();
        if (StrUtil.isNotBlank(result)) {
            copyToClipboard(result);
        }
    }

    /**
     * 添加事件监听器
     *
     * @param selectClassButton 选择类按钮
     * @param generateButton    生成按钮
     */
    private void addEventListeners(JButton selectClassButton, JButton generateButton) {
        selectClassButton.addActionListener(e -> {
            PsiClass selected = ClassChooseUtil.chooseClass(MessageUtil.getMessage("message.ChooseTarget"), project, selectedClass);
            if (selected != null) {
                selectedClass = selected;
                classField.setText(selected.getQualifiedName());
                genMockDataState.lastSelectedClass = selected.getQualifiedName();
            }
        });

        generateButton.addActionListener(e -> {
            if (selectedClass != null) {
                String mockJson = generateMockData(selectedClass).toString();
                resultTextArea.setText(mockJson);
                // 保存配置到状态
                saveConfigurationToState();
            }
        });
    }
    
    /**
     * 保存配置到状态
     */
    private void saveConfigurationToState() {
        genMockDataState.stringDefaultValue = stringDefaultValueField.getText();
        genMockDataState.stringRandom = stringRandomCheckBox.isSelected();
        genMockDataState.intMinValue = intMinValueField.getText();
        genMockDataState.intMaxValue = intMaxValueField.getText();
        genMockDataState.timeValue = (String) timeValueComboBox.getSelectedItem();
        genMockDataState.timeFormat = timeFormatField.getText();
        genMockDataState.timestamp = timestampCheckBox.isSelected();
        genMockDataState.nestedMock = nestedMockCheckBox.isSelected();
    }

    public static class GenMockDataState {
        public String lastSelectedClass = "";
        public String stringDefaultValue = "test";
        public boolean stringRandom = false;
        public String intMinValue = "1";
        public String intMaxValue = "100";
        public String timeValue = PAST;
        public String timeFormat = "yyyy-MM-dd HH:mm:ss";
        public boolean timestamp = false;
        public boolean nestedMock = true;
    }
}